// 19.5 嵌套类
/**
 * 嵌套类常用于定义作为实现部分的类，比如我们在文本查询示例中使用的QueryResult类（参见12.3节，第430页）。
 * 嵌套类是一个独立的类，与外层类基本没什么关系。特别是，外层类的对象和嵌套类的对象是相互独立的。在嵌套类的对象中不包含任何外层类定义的成员；类似的，在外层类的对象中也不包含任何嵌套类定义的成员。
 * 嵌套类的名字在外层类作用域中是可见的，在外层类作用域之外不可见。和其他嵌套的名字一样，嵌套类的名字不会和别的作用域中的同一个名字冲突。
 * 外层类对嵌套类的成员没有特殊的访问权限，同样，嵌套类对外层类的成员也没有特殊的访问权限。
 */

#include <iterator>
#include <vector>
#include <list>
#include <deque>
#include <forward_list>
#include <string>
#include <array>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
using std::swap;
using std::vector, std::list, std::deque, std::forward_list, std::string, std::array, std::stack, std::queue;
#include "../Chapter07/Sales_data.h"
#include <iostream>
using std::begin, std::cbegin, std::end, std::cend, std::find, std::accumulate, std::equal, std::fill, std::fill_n, std::back_inserter;
using std::cin, std::cout, std::endl;
using std::copy, std::replace, std::replace_copy;
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <memory>
#include <new>
using namespace std;
#include <functional>
#include "../VisualStudio2012/15/Quote.h"
#include "../VisualStudio2012/12/TextQuery.h"
#include <tuple>
#include <bitset>
#include <regex>
#include <random>
#include <cmath>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <typeinfo>

int main()
{
    // 声明一个嵌套类
    /*我们为12.3.2节（第432页）的TextQuery类定义了一个名为QueryResult的配套类，这两个类密切相关。QueryResult类的主要作用是表示TextQuery对象上query操作的结果，
        显然将QueryResult用作其他目的没有任何意义。为了充分体现这种紧密的相关性，我们可以把QueryResult定义成TextQuery的成员。[插图]
class TextQuery {
public:
    class QueryResult; // 嵌套类稍后定义
    // 其他成员与12.3.2节一致
};
    */

    // 在外层类之外定义一个嵌套类
    /*我们在TextQuery内声明了QueryResult，但是没有给出它的定义。和成员函数一样，嵌套类必须声明在类的内部，但是可以定义在类的内部或者外部。
        当我们在外层类之外定义一个嵌套类时，必须以外层类的名字限定嵌套类的名字：[插图]
// QueryResult是TextQuery的嵌套类
class TextQuery::QueryResult {
    // 位于类的作用域内，因此我们不必对QueryResult形参进行限定
    friend std::ostream& print(std::ostream&, const QueryResult&);
public:
    // 无需定义QueryResult::line_no
    // 嵌套类可以直接使用外层类的成员，无需对该成员的名字进行限定
    QueryResult(std::string, std::shared_ptr<std::set<line_no>>, std::shared_ptr<std::vector<std::string>>);
    // 其他成员与12.3.2节一致
}
      在嵌套类在其外层类之外完成真正的定义之前，它都是一个不完全类型（参见7.3.3节，第250页）
    */

    // 定义嵌套类的成员
    /*在这个版本的QueryResult类中，我们并没有在类的内部定义其构造函数。要想为其定义构造函数，必须指明QueryResult是嵌套在TextQuery的作用域之内的。具体做法是使用外层类的名字限定嵌套类的名字：[插图]
TextQuery::QueryResult::QueryResult(std::string s,
      std::shared_ptr<std::set<line_no>> p,
      std::shared_ptr<std::vector<std::string>> lines):
      sought(s), lines(p), file(f) { }
    */

    // 嵌套类的静态成员定义
    /*如果QueryResult声明了一个静态成员，则该成员的定义将位于TextQuery的作用域之外。例如，假设QueryResult有一个静态成员，则该成员的定义将形如：[插图]
// QueryResult类嵌套在TextQuery类中
// 下面的代码为QueryResult类定义一个静态成员
int TextQuery::QueryResult::static_mem = 1024;
    */

    // 嵌套类作用域中的名字查找
    /*如我们所知，嵌套类是其外层类的一个类型成员，因此外层类的成员可以像使用任何其他类型成员一样使用嵌套类的名字。
    */

    // 嵌套类和外层类是相互独立的
    /*尽管嵌套类定义在其外层类的作用域中，但是读者必须谨记外层类的对象和嵌套类的对象没有任何关系。嵌套类的对象只包含嵌套类定义的成员；
        同样，外层类的对象只包含外层类定义的成员，在外层类对象中不会有任何嵌套类的成员。
    */

    return 0;
}